package br.usp.ime.instrumentation;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import recoder.ParserException;
import recoder.ProgramFactory;
import recoder.abstraction.Method;
import recoder.java.CompilationUnit;
import recoder.java.ProgramElement;
import recoder.java.declaration.ClassDeclaration;
import recoder.kit.Transformation;
import br.usp.ime.lab.analyzer.ConditionAnalyzerImpl;

public class Instrumentation {
	Integer decisionID;
	static Instrumentation instance;
	
	public static Instrumentation getInstance() {
		if (instance == null) {
			instance = new Instrumentation();
		}
		return instance;
	}
	
	public Instrumentation() {}
	
	
	public void instrumentatePackage(String local, String pkg, String destination) throws ParserException {
		
	}
	
	
	public Map<String, Vector<Method>> getAst(String local, String pkg) {
		Map<String, Vector<Method>> methods = new HashMap<String, Vector<Method>>();
		File dir = new File(local);
		String dirString = dir.getAbsolutePath() + "/" + pkg.replaceAll("\\.", "/");
		dir = new File(dirString);
		File[] files = dir.listFiles();
		getMethods(files, methods);
		return methods;
	}
	
	
	private void getMethods (File[] files, Map<String, Vector<Method>> methods) {

		return;
	}
	
	/**
	 * M�todo de instrumenta��o que adiciona os imports de java.io no c�digo fonte
	 * @param Method um objeto Method referente a um m�todo
	 **/
	public CompilationUnit insertImport(Method m) {
		ProgramElement javaFile;
		for (javaFile = (ProgramElement)m; javaFile.getASTParent() != null; javaFile = javaFile.getASTParent());
		try {
			Transformation.doAttach(javaFile.getFactory().createImport(javaFile.getFactory().parsePackageReference("java.io.*")), (CompilationUnit) javaFile, 0);
		} catch (ParserException e) {
			e.printStackTrace();
		}
		return (CompilationUnit) javaFile;
	}
	
	
	public void instrumentateMethods(Vector<Method> methods, ProgramFactory programFactory) {

	}
	
	
	public void instrumentateDecisionStructure(ProgramElement dS, ConditionAnalyzerImpl conditionAnalyzer, ProgramFactory programFactory, Method m ) {

	}
	
	/**
	 * Devolve o nome da classe que cont�m o m�todo m
	 * @param m um objeto Method do Recoder 
	 **/
	public String getClassName(Method m) {
		ProgramElement p = (ProgramElement)m;
		ClassDeclaration classDecl;
		while (!(p.getASTParent() instanceof ClassDeclaration)) {
			p = p.getASTParent();
		}
		classDecl = (ClassDeclaration) p.getASTParent();
		return classDecl.getName();
	}
}
